home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 October: Technology Seed / ADC Seed CD - October 1999.toast / FireWire / FireWire_2.0_SDK / Source / SBP2 / SampleSBP2Family / SampleSBP2Family.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-04-12  |  26.1 KB  |  1,087 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        SampleSBP2Family.c
  3.  
  4.     Contains:    Sample family for Serial Bus Protocol 2 (SBP-2)
  5.  
  6.     Version:    1.0
  7.  
  8.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                Eric Anderson
  13.  
  14.         Other Contact:        
  15.  
  16.         Technology:            FireWire
  17.  
  18.     Writers:
  19.  
  20.         (EA)    Eric Anderson (ewa)
  21.         (EA)    Eric Anderson (ewa)
  22.  
  23.     Change History (most recent first):
  24.  
  25.        <FW3>     1/15/99    EA        Fix uninitialized variable problem.
  26.        <FW2>     9/20/98    EA        Filled in header comments.
  27.        <FW1>     9/20/98    EA        first checked in
  28. */
  29.  
  30.  
  31. #include <Types.h>
  32. #include <Errors.h>
  33. #include <Strings.h>
  34. #include <Traps.h>
  35. #include <Events.h>
  36. #include <Processes.h>
  37. #include <AppleEvents.h>
  38. #include <Devices.h>
  39. #include <CodeFragments.h>
  40. #include <DriverServices.h>
  41. #include <NameRegistry.h>
  42. #include <GenericDriverFamily.h>
  43. #include <SampleSBP2.h>
  44. #include <SampleSBP2Priv.h>
  45. #include <SampleSBP2Expert.h>
  46.  
  47. ////////////////////////////////////////////////////////////////////////////////
  48. //
  49. // Define global structure to hold all of the Sample SBP
  50. // Family data.
  51. //
  52.  
  53. SBPFamilyDataPtr                gpSBPFamilyData = nil;
  54. SBPExpertDataPtr                gpSBPExpertData = nil;
  55.  
  56.  
  57. ////////////////////////////////////////////////////////////////////////////////
  58. //
  59. // Internal routine prototypes.
  60. //
  61.  
  62. static OSStatus    SBPEventHandler (
  63.     GDFDeviceEventDataPtr        pGDFDeviceEventData);
  64.  
  65. static OSStatus    SBPHandleDeviceAdded (
  66.     GDFDeviceEventDataPtr        pGDFDeviceEventData);
  67.  
  68. static OSStatus    SBPHandleDeviceRemoved (
  69.     GDFDeviceEventDataPtr        pGDFDeviceEventData);
  70.  
  71. static OSErr    SBPSendClientAppleEvent (
  72.     SBPClientDataPtr            pSBPClientData,
  73.     const AppleEvent            *theAppleEvent,
  74.     AESendMode                    sendMode,
  75.     AESendPriority                sendPriority,
  76.     long                        timeOutInTicks,
  77.     AEIdleUPP                    idleProc,
  78.     AEFilterUPP                    filterProc);
  79.  
  80. static void    DisposeClientAppleEventData (
  81.     ClientAppleEventDataPtr        pClientAppleEventData);
  82.  
  83. static OSStatus    SBPCreateClientAppleEventQueue (
  84.     SBPClientDataPtr            pSBPClientData);
  85.  
  86. static OSStatus    SBPDisposeClientAppleEventQueue (
  87.     SBPClientDataPtr            pSBPClientData);
  88.  
  89. static OSStatus    SBPAddDriver (
  90.     GDFDeviceEventDataPtr        pGDFDeviceEventData,
  91.     SBPDriverID                    *pSBPDriverID);
  92.  
  93. static OSStatus    CreateSBPDriverID (
  94.     SBPDriverID                    *pSBPDriverID);
  95.  
  96. static void    DisposeSBPDriver (
  97.     SBPDriverID                    sbpDriverID);
  98.  
  99. static SBPDriverID    SBPFindDriver (
  100.     RegEntryIDPtr                pRegEntryID);
  101.  
  102.  
  103. ////////////////////////////////////////////////////////////////////////////////
  104. ////////////////////////////////////////////////////////////////////////////////
  105. //
  106. // Public routines.
  107. //
  108. ////////////////////////////////////////////////////////////////////////////////
  109. ////////////////////////////////////////////////////////////////////////////////
  110.  
  111. ////////////////////////////////////////////////////////////////////////////////
  112. //
  113. // RegisterSBPClientApplication
  114. //
  115. //   This routine registers the calling application as a client of the
  116. // Sample SBP family.
  117. //
  118.  
  119. OSStatus    RegisterSBPClientApplication(
  120.     SBPClientID                    *pSBPClientID,
  121.     UInt32                        clientContextData)
  122. {
  123.     SBPClientID                    sbpClientID = kInvalidSBPClientID;
  124.     SBPClientDataPtr            pSBPClientData = nil,
  125.                                 pNextSBPClientData;
  126.     ProcessSerialNumber            currentPSN;
  127.     OSStatus                    status = noErr;
  128.  
  129.     // Allocate client data record.
  130.     pSBPClientData =
  131.         (SBPClientDataPtr) PoolAllocateResident (sizeof (SBPClientData), true);
  132.     if (pSBPClientData != nil)
  133.     {
  134.         pSBPClientData->clientContextData = clientContextData;
  135.         sbpClientID = (SBPClientID) pSBPClientData;
  136.     }
  137.     else
  138.     {
  139.         status = memFullErr;
  140.     }
  141.  
  142.     // Add client data record to list.
  143.     if (status == noErr)
  144.     {
  145.         pNextSBPClientData = gpSBPFamilyData->pSBPClientList;
  146.         if (pNextSBPClientData != nil)
  147.             pNextSBPClientData->pPrevSBPClientData = pSBPClientData;
  148.  
  149.         pSBPClientData->pPrevSBPClientData = nil;
  150.         pSBPClientData->pNextSBPClientData = pNextSBPClientData;
  151.         gpSBPFamilyData->pSBPClientList = pSBPClientData;
  152.     }
  153.  
  154.     // Create client Apple Event queue.
  155.     if (status == noErr)
  156.         status = SBPCreateClientAppleEventQueue (pSBPClientData);
  157.  
  158.     // Create an Apple Event target descriptor for the client.
  159.     if (status == noErr)
  160.     {
  161.         status = GetCurrentProcess (¤tPSN);
  162.  
  163.         if (status == noErr)
  164.         {
  165.             status = AECreateDesc (typeProcessSerialNumber,
  166.                                    ¤tPSN,
  167.                                    sizeof (ProcessSerialNumber),
  168.                                    &(pSBPClientData->clientAEAddress));
  169.             if (status == noErr)
  170.                 pSBPClientData->clientAEAddressValid = true;
  171.         }
  172.     }
  173.  
  174.     // Create an Apple Event for device added notification.
  175.     if (status == noErr)
  176.     {
  177.         status = AECreateAppleEvent
  178.                     (kAESampleSBP2EventClass,
  179.                      kAESampleSBP2DeviceAdded,
  180.                      &(pSBPClientData->clientAEAddress),
  181.                      kAutoGenerateReturnID,
  182.                      kAnyTransactionID,
  183.                      &(pSBPClientData->deviceAddedAppleEvent));
  184.         if (status == noErr)
  185.             pSBPClientData->deviceAddedAppleEventValid = true;
  186.     }
  187.  
  188.     // Create an Apple Event for device removed notification.
  189.     if (status == noErr)
  190.     {
  191.         status = AECreateAppleEvent
  192.                     (kAESampleSBP2EventClass,
  193.                      kAESampleSBP2DeviceRemoved,
  194.                      &(pSBPClientData->clientAEAddress),
  195.                      kAutoGenerateReturnID,
  196.                      kAnyTransactionID,
  197.                      &(pSBPClientData->deviceRemovedAppleEvent));
  198.         if (status == noErr)
  199.             pSBPClientData->deviceRemovedAppleEventValid = true;
  200.     }
  201.  
  202.     // Clean up on error.
  203.     if (status != noErr)
  204.     {
  205.         if (sbpClientID != kInvalidSBPClientID)
  206.             UnregisterSBPClientApplication (sbpClientID);
  207.     }
  208.  
  209.     // Return results.
  210.     *pSBPClientID = sbpClientID;
  211.  
  212.     return (status);
  213. }
  214.  
  215.  
  216. ////////////////////////////////////////////////////////////////////////////////
  217. //
  218. // UnregisterSBPClientApplication
  219. //
  220. //   This routine unregisters the calling application as a client of the
  221. // Sample SBP family.
  222. //
  223.  
  224. OSStatus    UnregisterSBPClientApplication(
  225.     SBPClientID                    sbpClientID)
  226. {
  227.     SBPClientDataPtr            pSBPClientData,
  228.                                 pPrevSBPClientData,
  229.                                 pNextSBPClientData;
  230.     OSStatus                    status = noErr;
  231.  
  232.     if (sbpClientID != kInvalidSBPClientID)
  233.     {
  234.         // Get client data from ID.
  235.         pSBPClientData = (SBPClientDataPtr) sbpClientID;
  236.  
  237.         // Deallocate device removed Apple Event.
  238.         if (pSBPClientData->deviceRemovedAppleEventValid)
  239.             AEDisposeDesc (&(pSBPClientData->deviceRemovedAppleEvent));
  240.  
  241.         // Deallocate device added Apple Event.
  242.         if (pSBPClientData->deviceAddedAppleEventValid)
  243.             AEDisposeDesc (&(pSBPClientData->deviceAddedAppleEvent));
  244.  
  245.         // Deallocate target descriptor.
  246.         if (pSBPClientData->clientAEAddressValid)
  247.             AEDisposeDesc (&(pSBPClientData->clientAEAddress));
  248.  
  249.         // Dispose of client Apple Event queue.
  250.         if (pSBPClientData->clientAppleEventQueue != nil)
  251.             SBPDisposeClientAppleEventQueue (pSBPClientData);
  252.  
  253.         // Remove client from list.
  254.         pPrevSBPClientData = pSBPClientData->pPrevSBPClientData;
  255.         pNextSBPClientData = pSBPClientData->pNextSBPClientData;
  256.  
  257.         if (pPrevSBPClientData != nil)
  258.             pPrevSBPClientData->pNextSBPClientData = pNextSBPClientData;
  259.         else
  260.             gpSBPFamilyData->pSBPClientList = pNextSBPClientData;
  261.  
  262.         if (pNextSBPClientData != nil)
  263.             pNextSBPClientData->pPrevSBPClientData = pPrevSBPClientData;
  264.  
  265.         // Deallocate client data record.
  266.         PoolDeallocate ((Ptr) pSBPClientData);
  267.     }
  268.  
  269.     return (status);
  270. }
  271.  
  272.  
  273. ////////////////////////////////////////////////////////////////////////////////
  274. //
  275. // GetSBPDriverList
  276. //
  277. //   This routine returns a list of Sample SBP driver IDs and the
  278. // number of drivers installed in the system.
  279. //
  280.  
  281. OSStatus    GetSBPDriverList(
  282.     SBPDriverID                    *pSBPDriverIDList,
  283.     UInt32                        sbpDriverIDListSize,
  284.     UInt32                        *pNumSBPDrivers)
  285. {
  286.     SBPDriverDataPtr            pSBPDriverData;
  287.     UInt32                        numSBPDrivers,
  288.                                 numSBPDriversInList,
  289.                                 driverNum;
  290.     OSStatus                    status = noErr;
  291.  
  292.     // Compute number of drivers to put in list.
  293.     numSBPDrivers = gpSBPFamilyData->numSBPDrivers;
  294.     numSBPDriversInList = sbpDriverIDListSize;
  295.     if (numSBPDriversInList > numSBPDrivers)
  296.         numSBPDriversInList = numSBPDrivers;
  297.  
  298.     // Copy driver IDs in order.
  299.     pSBPDriverData = gpSBPFamilyData->pSBPDriverList;
  300.     for (driverNum = 0; driverNum < numSBPDriversInList; driverNum++)
  301.     {
  302.         pSBPDriverIDList[driverNum] = (SBPDriverID) pSBPDriverData;
  303.         pSBPDriverData = pSBPDriverData->pNextSBPDriverData;
  304.     }
  305.  
  306.     // Return number of installed drivers.
  307.     *pNumSBPDrivers = numSBPDrivers;
  308.  
  309.     return (status);
  310. }
  311.  
  312.  
  313. ////////////////////////////////////////////////////////////////////////////////
  314. //
  315. // CallSBPDriver
  316. //
  317. //   This routine sends a request to the given driver.
  318. //
  319.  
  320. OSStatus    CallSBPDriver(
  321.     SBPDriverID                    sbpDriverID,
  322.     SBPInterfaceParamsPtr        pSBPInterfaceParams)
  323. {
  324.     SBPDriverDataPtr            pSBPDriverData;
  325.     CntrlParam                    cntrlParam;
  326.     OSStatus                    status = noErr;
  327.  
  328.     // Get the driver data from the ID.
  329.     pSBPDriverData = (SBPDriverDataPtr) sbpDriverID;
  330.  
  331. /*zzz*/
  332.     if (pSBPDriverData->deviceDisconnected)
  333.         return (-139);//zzz need disconnectedErr
  334. /*zzz*/
  335.     // Set up control parameters.
  336.     cntrlParam.ioCompletion = nil;
  337.     cntrlParam.ioVRefNum = 0;
  338.     cntrlParam.ioCRefNum = pSBPDriverData->driverRefNum;
  339.     cntrlParam.csCode = cscSBPCommand;
  340.     *((Ptr *) &(cntrlParam.csParam[0])) = (Ptr) pSBPInterfaceParams;
  341.  
  342.     // Call the driver.
  343.     status = PBControlSync ((ParmBlkPtr) &cntrlParam);
  344.  
  345.     return (status);
  346. }
  347.  
  348.  
  349. ////////////////////////////////////////////////////////////////////////////////
  350. //
  351. // OpenSBPDriver
  352. //
  353. //   This routine opens a connection to the given driver.
  354. //
  355.  
  356. OSStatus    OpenSBPDriver (
  357.     SBPDriverID                    sbpDriverID)
  358. {
  359.     SBPDriverDataPtr            pSBPDriverData;
  360.     OSStatus                    status = noErr;
  361.  
  362.     // Get the driver data from the ID.
  363.     pSBPDriverData = (SBPDriverDataPtr) sbpDriverID;
  364.  
  365.     // One more connection.
  366.     pSBPDriverData->numConnections++;
  367.  
  368.     return (status);
  369. }
  370.  
  371.  
  372. ////////////////////////////////////////////////////////////////////////////////
  373. //
  374. // CloseSBPDriver
  375. //
  376. //   This routine closes a connection to the given driver.
  377. //
  378.  
  379. OSStatus    CloseSBPDriver (
  380.     SBPDriverID                    sbpDriverID)
  381. {
  382.     SBPDriverDataPtr            pSBPDriverData;
  383.     OSStatus                    status = noErr;
  384.  
  385.     // Get the driver data from the ID.
  386.     pSBPDriverData = (SBPDriverDataPtr) sbpDriverID;
  387.  
  388.     // One less connection.
  389.     pSBPDriverData->numConnections--;
  390.  
  391.     // Dispose driver if device has been disconnected.
  392.     if ((pSBPDriverData->deviceDisconnected) && (pSBPDriverData->numConnections == 0))
  393.         DisposeSBPDriver (sbpDriverID);
  394.  
  395.     return (status);
  396. }
  397.  
  398.  
  399. ////////////////////////////////////////////////////////////////////////////////
  400. //
  401. // GetNextSBPClientEvent
  402. //
  403. //   This routine checks if any client Apple Events are pending and sends any
  404. // that are.
  405. //
  406.  
  407. OSStatus    GetNextSBPClientEvent(
  408.     SBPClientID                    sbpClientID)
  409. {
  410.     SBPClientDataPtr            pSBPClientData;
  411.     ClientAppleEventDataPtr        pClientAppleEventData;
  412.     AppleEvent                    reply;
  413.     OSStatus                    status = noErr,
  414.                                 queueStatus = noErr;
  415.  
  416.     // Get client data from ID.
  417.     pSBPClientData = (SBPClientDataPtr) sbpClientID;
  418.  
  419.     // Send any client Apple Events on queue.
  420.     while (queueStatus == noErr)
  421.     {
  422.         queueStatus = PBDequeueFirst (pSBPClientData->clientAppleEventQueue,
  423.                                       (QElemPtr *) &pClientAppleEventData);
  424.         if (queueStatus == noErr)
  425.         {
  426.             // Send the Apple Event.
  427.             AESend (&(pClientAppleEventData->clientAppleEvent),
  428.                     &reply,
  429.                     pClientAppleEventData->sendMode,
  430.                     pClientAppleEventData->sendPriority,
  431.                     pClientAppleEventData->timeOutInTicks,
  432.                     pClientAppleEventData->idleProc,
  433.                     pClientAppleEventData->filterProc);
  434.  
  435.             // Dispose of reply.
  436.             AEDisposeDesc (&reply);
  437.  
  438.             // We're now done with the client Apple Event data record.
  439.             DisposeClientAppleEventData (pClientAppleEventData);
  440.         }
  441.     }
  442.  
  443.     return (status);
  444. }
  445.  
  446.  
  447. ////////////////////////////////////////////////////////////////////////////////
  448. ////////////////////////////////////////////////////////////////////////////////
  449. //
  450. // Private routines.
  451. //
  452. ////////////////////////////////////////////////////////////////////////////////
  453. ////////////////////////////////////////////////////////////////////////////////
  454.  
  455. ////////////////////////////////////////////////////////////////////////////////
  456. //
  457. // InitializeSBPFamily
  458. //
  459. //   This routine initializes the Sample SBP family.
  460. //
  461.  
  462. long    InitializeSBPFamily(void)
  463. {
  464.     OSStatus                    status = noErr;
  465.  
  466.     // Allocate family global record.
  467.     gpSBPFamilyData =
  468.         (SBPFamilyDataPtr) PoolAllocateResident (sizeof (SBPFamilyData), true);
  469.     if (gpSBPFamilyData == nil)
  470.         status = memFullErr;
  471.  
  472.     return ((long) status);
  473. }
  474.  
  475.  
  476. ////////////////////////////////////////////////////////////////////////////////
  477. //
  478. // TerminateSBPFamily
  479. //
  480. //   This routine terminates the Sample SBP family.
  481. //
  482.  
  483. long    TerminateSBPFamily(void)
  484. {
  485.     OSStatus                    status = noErr;
  486.  
  487.     // Deallocate family global record.
  488.     if (gpSBPFamilyData != nil)
  489.         PoolDeallocate ((Ptr) gpSBPFamilyData);
  490.  
  491.     return ((long) status);
  492. }
  493.  
  494.  
  495. ////////////////////////////////////////////////////////////////////////////////
  496. //
  497. // InstallSBPExpert
  498. //
  499. //   This routine installs the Sample SBP expert loading
  500. // mechanism.
  501. //
  502.  
  503. OSStatus    InstallSBPExpert(void)
  504. {
  505.     UInt32                        eventTable[1];
  506.     OSStatus                    status = noErr;
  507.  
  508.     gpSBPExpertData =
  509.         (SBPExpertDataPtr) PoolAllocateResident (sizeof (SBPExpertData), true);
  510.     if (gpSBPExpertData == nil)
  511.         status = memFullErr;
  512.  
  513.     // Register to receive generic device added events.
  514.     if (status == noErr)
  515.     {
  516.         eventTable[0] = kGDFDeviceAddedEvent;
  517.         eventTable[1] = kGDFDeviceRemovedEvent;
  518.         status = GDFRegisterDeviceEventHandlerProc
  519.                     (kNdrvTypeIsSampleSBP2,
  520.                      2,
  521.                      &eventTable[0],
  522.                      SBPEventHandler,
  523.                      nil,
  524.                      &(gpSBPExpertData->gdfDeviceEventRegistrationID));
  525.     }
  526.     
  527.     return status;
  528. }
  529.  
  530.  
  531. ////////////////////////////////////////////////////////////////////////////////
  532. //
  533. // UninstallSBPExpert
  534. //
  535. //   This routine uninstalls the Sample SBP expert loading
  536. // mechanism.
  537. //
  538.  
  539. OSStatus    UninstallSBPExpert(void)
  540. {
  541.     OSStatus                    status = noErr;
  542.  
  543.     // Dispose of SBPExpert data.
  544.     if (gpSBPExpertData != nil)
  545.     {
  546.         // Unregister with Generic Device family.
  547.         if (gpSBPExpertData->gdfDeviceEventRegistrationID !=
  548.             kInvalidGDFDeviceEventRegistrationID)
  549.         {
  550.             status = GDFUnregisterDeviceEventHandler
  551.                         (gpSBPExpertData->gdfDeviceEventRegistrationID);
  552.         }
  553.  
  554.         PoolDeallocate ((Ptr) gpSBPExpertData);
  555.         gpSBPExpertData = nil;
  556.     }
  557.  
  558.     return (status);
  559. }
  560.  
  561.  
  562. ////////////////////////////////////////////////////////////////////////////////
  563. ////////////////////////////////////////////////////////////////////////////////
  564. //
  565. // Internal routines.
  566. //
  567. ////////////////////////////////////////////////////////////////////////////////
  568. ////////////////////////////////////////////////////////////////////////////////
  569.  
  570. ////////////////////////////////////////////////////////////////////////////////
  571. //
  572. // SBPEventHandler
  573. //
  574. //   This proc handles device events for Sample SBP devices.
  575. //
  576.  
  577. static OSStatus    SBPEventHandler(
  578.     GDFDeviceEventDataPtr        pGDFDeviceEventData)
  579. {
  580.     OSStatus                    status = noErr;
  581.  
  582.     // Dispatch off of device event.
  583.     switch (pGDFDeviceEventData->deviceEvent)
  584.     {
  585.         case kGDFDeviceAddedEvent :
  586.             status = SBPHandleDeviceAdded (pGDFDeviceEventData);
  587.             break;
  588.  
  589.         case kGDFDeviceRemovedEvent :
  590.             status = SBPHandleDeviceRemoved (pGDFDeviceEventData);
  591.             break;
  592.  
  593.         default :
  594.             break;
  595.     }
  596.  
  597.     return (status);
  598. }
  599.  
  600.  
  601. ////////////////////////////////////////////////////////////////////////////////
  602. //
  603. // SBPHandleDeviceAdded
  604. //
  605. //   This routine handles new devices being added.
  606. //
  607.  
  608. static OSStatus    SBPHandleDeviceAdded(
  609.     GDFDeviceEventDataPtr        pGDFDeviceEventData)
  610. {
  611.     SBPDriverID                    SBPDriverID;
  612.     SBPDriverDataPtr            pSBPDriverData;
  613.  
  614.     SBPClientDataPtr            pSBPClientData;
  615.  
  616.     OSStatus                    status = noErr,
  617.                                 clientStatus;
  618.  
  619.     // Check if SBP driver is in our list.  This will happen if device was
  620.     // connected, opened, disconnected, and reconnected without being closed.
  621.     // If it's in our list, set disconnected to false.
  622.     SBPDriverID = SBPFindDriver (&(pGDFDeviceEventData->deviceRegEntryID));
  623.     if (SBPDriverID != kInvalidSBPDriverID)
  624.     {
  625.         pSBPDriverData = (SBPDriverDataPtr) SBPDriverID;
  626.         pSBPDriverData->deviceDisconnected = false;
  627.     }
  628.     else
  629.     {
  630.         status = SBPAddDriver (pGDFDeviceEventData, &SBPDriverID);
  631.         if (status == noErr)
  632.             pSBPDriverData = (SBPDriverDataPtr) SBPDriverID;
  633.     }
  634.  
  635.     // Send up notification to all clients.
  636.     if (status == noErr)
  637.     {
  638.         pSBPClientData = gpSBPFamilyData->pSBPClientList;
  639.         while (pSBPClientData != nil)
  640.         {
  641.             // Add the driver ID parameter to event.
  642.             clientStatus = AEPutParamPtr
  643.                             (&(pSBPClientData->deviceAddedAppleEvent),
  644.                              kAESBPDriverIDKey,
  645.                              kAESBPDriverIDType,
  646.                              &SBPDriverID,
  647.                              sizeof (SBPDriverID));
  648.  
  649.             // Send event.
  650.             if (clientStatus == noErr)
  651.             {
  652.                 clientStatus = SBPSendClientAppleEvent
  653.                                 (pSBPClientData,
  654.                                  &(pSBPClientData->deviceAddedAppleEvent),
  655.                                  0,
  656.                                  kAENormalPriority,
  657.                                  0,
  658.                                  nil,
  659.                                  nil);
  660.             }
  661.  
  662.             pSBPClientData = pSBPClientData->pNextSBPClientData;
  663.         }
  664.     }
  665.  
  666.     return (status);
  667. }
  668.  
  669.  
  670. ////////////////////////////////////////////////////////////////////////////////
  671. //
  672. // SBPHandleDeviceRemoved
  673. //
  674. //   This routine handles devices being removed.
  675. //
  676.  
  677. static OSStatus    SBPHandleDeviceRemoved(
  678.     GDFDeviceEventDataPtr        pGDFDeviceEventData)
  679. {
  680.     RegEntryIDPtr                pRegEntryID;
  681.     SBPDriverID                    sbpDriverID;
  682.     SBPDriverDataPtr            pSBPDriverData;
  683.     SBPClientDataPtr            pSBPClientData;
  684.     Boolean                        found;
  685.     OSStatus                    status = noErr,
  686.                                 clientStatus;
  687.  
  688.     // Get Name Registry entry.
  689.     pRegEntryID = &(pGDFDeviceEventData->deviceRegEntryID);
  690.  
  691.     // Find driver that is being removed.
  692.     sbpDriverID = SBPFindDriver (pRegEntryID);
  693.     if (sbpDriverID != kInvalidSBPDriverID)
  694.     {
  695.         pSBPDriverData = (SBPDriverDataPtr) sbpDriverID;
  696.         found = true;
  697.     }
  698.     else
  699.     {
  700.         found = false;
  701.     }
  702.  
  703.     // If driver was found, set it disconnected.
  704.     if (found)
  705.         pSBPDriverData->deviceDisconnected = true;
  706.  
  707.     // Dispose driver if no one has it open.
  708.     // Otherwise, send up notification to all clients.
  709.     if (found)
  710.     {
  711.         if (pSBPDriverData->numConnections == 0)
  712.         {
  713.             DisposeSBPDriver ((SBPDriverID) pSBPDriverData);
  714.         }
  715.         else
  716.         {
  717.             pSBPClientData = gpSBPFamilyData->pSBPClientList;
  718.             while (pSBPClientData != nil)
  719.             {
  720.                 // Add the driver ID parameter to event.
  721.                 clientStatus = AEPutParamPtr
  722.                                 (&(pSBPClientData->deviceRemovedAppleEvent),
  723.                                  kAESBPDriverIDKey,
  724.                                  kAESBPDriverIDType,
  725.                                  &sbpDriverID,
  726.                                  sizeof (SBPDriverID));
  727.  
  728.                 // Send event.
  729.                 if (clientStatus == noErr)
  730.                 {
  731.                     clientStatus = SBPSendClientAppleEvent
  732.                                     (pSBPClientData,
  733.                                      &(pSBPClientData->deviceRemovedAppleEvent),
  734.                                      0,
  735.                                      kAENormalPriority,
  736.                                      0,
  737.                                      nil,
  738.                                      nil);
  739.                 }
  740.  
  741.                 pSBPClientData = pSBPClientData->pNextSBPClientData;
  742.             }
  743.         }
  744.     }
  745.  
  746.     return (status);
  747. }
  748.  
  749.  
  750. ////////////////////////////////////////////////////////////////////////////////
  751. //
  752. // SBPSendClientAppleEvent
  753. //
  754. //   This routine queues an Apple Event to be sent to a client for device
  755. // notification.
  756. //
  757.  
  758. static OSErr    SBPSendClientAppleEvent(
  759.     SBPClientDataPtr            pSBPClientData,
  760.     const AppleEvent            *theAppleEvent,
  761.     AESendMode                    sendMode,
  762.     AESendPriority                sendPriority,
  763.     long                        timeOutInTicks,
  764.     AEIdleUPP                    idleProc,
  765.     AEFilterUPP                    filterProc)
  766. {
  767.     ClientAppleEventDataPtr        pClientAppleEventData = nil;    
  768.     OSErr                        err = noErr;
  769.  
  770.     // Create data for the client Apple Event.
  771.     pClientAppleEventData = (ClientAppleEventDataPtr)
  772.         PoolAllocateResident (sizeof (ClientAppleEventData), true);
  773.     if (pClientAppleEventData != nil)
  774.     {
  775.         pClientAppleEventData->sendMode =
  776.             (sendMode & ~(kAENoReply | kAEQueueReply | kAEWaitReply)) | kAENoReply;
  777.         pClientAppleEventData->sendPriority = sendPriority;
  778.         pClientAppleEventData->timeOutInTicks = timeOutInTicks;
  779.         pClientAppleEventData->idleProc = idleProc;
  780.         pClientAppleEventData->filterProc = filterProc;
  781.     }
  782.     else
  783.     {
  784.         err = memFullErr;
  785.     }
  786.  
  787.     // Copy the given Apple Event.
  788.     if (err == noErr)
  789.     {
  790.         err = AEDuplicateDesc (theAppleEvent,
  791.                                &(pClientAppleEventData->clientAppleEvent));
  792.         if (err == noErr)
  793.             pClientAppleEventData->clientAppleEventValid = true;
  794.     }
  795.  
  796.     // Queue the client Apple Event to be sent at a good time.
  797.     if (err == noErr)
  798.     {
  799.         err = PBEnqueueLast ((QElemPtr) pClientAppleEventData,
  800.                              pSBPClientData->clientAppleEventQueue);
  801.     }
  802.  
  803.     // Clean up on error.
  804.     if (err != noErr)
  805.         DisposeClientAppleEventData (pClientAppleEventData);
  806.  
  807.     return (err);
  808. }
  809.  
  810.  
  811. ////////////////////////////////////////////////////////////////////////////////
  812. //
  813. // DisposeClientAppleEventData
  814. //
  815. //   This routine disposes of the client Apple Event record.
  816. //
  817.  
  818. static void    DisposeClientAppleEventData(
  819.     ClientAppleEventDataPtr        pClientAppleEventData)
  820. {
  821.     if (pClientAppleEventData != nil)
  822.     {
  823.         // Dispose of Apple Event copy.
  824.         if (pClientAppleEventData->clientAppleEventValid)
  825.             AEDisposeDesc (&(pClientAppleEventData->clientAppleEvent));
  826.  
  827.         // Dispose of client Apple Event data record.
  828.         PoolDeallocate ((Ptr) pClientAppleEventData);
  829.     }
  830. }
  831.  
  832.  
  833. ////////////////////////////////////////////////////////////////////////////////
  834. //
  835. // SBPCreateClientAppleEventQueue
  836. //
  837. //   This routine creates a client AppleEvent queue.
  838. //
  839.  
  840. static OSStatus    SBPCreateClientAppleEventQueue(
  841.     SBPClientDataPtr            pSBPClientData)
  842. {
  843.     OSStatus                    status = noErr;
  844.  
  845.     status = PBQueueCreate (&(pSBPClientData->clientAppleEventQueue));
  846.  
  847.     return (status);
  848. }
  849.  
  850.  
  851. ////////////////////////////////////////////////////////////////////////////////
  852. //
  853. // SBPDisposeClientAppleEventQueue
  854. //
  855. //   This routine disposes of a client AppleEvent queue.
  856. //
  857.  
  858. static OSStatus    SBPDisposeClientAppleEventQueue(
  859.     SBPClientDataPtr            pSBPClientData)
  860. {
  861.     ClientAppleEventDataPtr        pClientAppleEventData;
  862.     OSStatus                    status = noErr;
  863.  
  864.     if (pSBPClientData->clientAppleEventQueue != nil)
  865.     {
  866.         // Dispose of any client AppleEvents still in queue.
  867.         while (status == noErr)
  868.         {
  869.             status = PBDequeueFirst (pSBPClientData->clientAppleEventQueue,
  870.                                      (QElemPtr *) &pClientAppleEventData);
  871.             if (status == noErr)
  872.                 DisposeClientAppleEventData (pClientAppleEventData);
  873.         }
  874.  
  875.         // Delete queue.
  876.         PBQueueDelete (pSBPClientData->clientAppleEventQueue);
  877.     }
  878.  
  879.     return (status);
  880. }
  881.  
  882.  
  883. ////////////////////////////////////////////////////////////////////////////////
  884. //
  885. // SBPAddDriver
  886. //
  887. //   This routine adds a new driver.
  888. //
  889.  
  890. static OSStatus    SBPAddDriver(
  891.     GDFDeviceEventDataPtr        pGDFDeviceEventData,
  892.     SBPDriverID                    *pSBPDriverID)
  893. {
  894.     RegEntryIDPtr                pRegEntryID;
  895.     SBPDriverID                    sbpDriverID = kInvalidSBPDriverID;
  896.     SBPDriverDataPtr            pSBPDriverData;
  897.  
  898.     OSStatus                    status = noErr;
  899.  
  900.     // Get Name Registry entry.
  901.     pRegEntryID = &(pGDFDeviceEventData->deviceRegEntryID);
  902.  
  903.     // Add driver record to list.
  904.     if (status == noErr)
  905.         status = CreateSBPDriverID (&sbpDriverID);
  906.  
  907.     // Get the driver data from the ID.
  908.     if (status == noErr)
  909.         pSBPDriverData = (SBPDriverDataPtr) sbpDriverID;
  910.  
  911.     // Fill in driver data record.
  912.     if (status == noErr)
  913.     {
  914.         pSBPDriverData->deviceRegistryID = *pRegEntryID;
  915.         pSBPDriverData->driverRefNum = pGDFDeviceEventData->driverRefNum;
  916.     }
  917.  
  918.     // Open driver.
  919.     if (status == noErr)
  920.     {
  921.         status = OpenInstalledDriver (pGDFDeviceEventData->driverRefNum, fsRdWrPerm);
  922.         if (status == noErr)
  923.             pSBPDriverData->driverOpened = true;
  924.     }
  925.  
  926.     // Clean up on error.
  927.     if (status != noErr)
  928.     {
  929.         if (sbpDriverID != kInvalidSBPDriverID)
  930.             DisposeSBPDriver (sbpDriverID);
  931.     }
  932.  
  933.     // Return results.
  934.     if (status == noErr)
  935.         *pSBPDriverID = sbpDriverID;
  936.     else
  937.         *pSBPDriverID = kInvalidSBPDriverID;
  938.  
  939.     return (status);
  940. }
  941.  
  942.  
  943. ////////////////////////////////////////////////////////////////////////////////
  944. //
  945. // CreateSBPDriverID
  946. //
  947. //   This routine creates a new Sample SBP driver record, adds it to
  948. // the family list, and returns the ID for the new driver record.
  949. //
  950.  
  951. static OSStatus    CreateSBPDriverID(
  952.     SBPDriverID                    *pSBPDriverID)
  953. {
  954.     SBPDriverDataPtr            pSBPDriverData = nil,
  955.                                 pNextSBPDriverData;
  956.     OSStatus                    status = noErr;
  957.  
  958.     // Allocate Sample SBP driver record.
  959.     pSBPDriverData = (SBPDriverDataPtr)
  960.         PoolAllocateResident (sizeof (SBPDriverData), true);
  961.     if (pSBPDriverData != nil)
  962.         pSBPDriverData->sbpDriverID = (SBPDriverID) pSBPDriverData;
  963.     else
  964.         status = memFullErr;
  965.  
  966.     // Add driver record to family list.
  967.     if (status == noErr)
  968.     {
  969.         pNextSBPDriverData = gpSBPFamilyData->pSBPDriverList;
  970.         pSBPDriverData->pNextSBPDriverData = pNextSBPDriverData;
  971.         gpSBPFamilyData->pSBPDriverList = pSBPDriverData;
  972.         gpSBPFamilyData->numSBPDrivers++;
  973.     }
  974.  
  975.     // Return result and clean up on error.
  976.     if (status == noErr)
  977.     {
  978.         *pSBPDriverID = pSBPDriverData->sbpDriverID;
  979.     }
  980.     else
  981.     {
  982.         if (pSBPDriverData != nil)
  983.             PoolDeallocate ((Ptr) pSBPDriverData);
  984.  
  985.         *pSBPDriverID = kInvalidSBPDriverID;
  986.     }
  987.  
  988.     return (status);
  989. }
  990.  
  991.  
  992. ////////////////////////////////////////////////////////////////////////////////
  993. //
  994. // DisposeSBPDriver
  995. //
  996. //   This routine disposes of the given driver.  It will call the driver to
  997. // terminate itself, dispose of the driver memory closure, remove the driver
  998. // data record from our list, and dispose of the driver data record.
  999. //
  1000.  
  1001. static void    DisposeSBPDriver(
  1002.     SBPDriverID                    sbpDriverID)
  1003. {
  1004.     SBPDriverDataPtr            pSBPDriverData,
  1005.                                 pSearchSBPDriverData,
  1006.                                 pPrevSBPDriverData;
  1007.     THz                            currentZone;
  1008.  
  1009.     // Switch to system zone.
  1010.     currentZone = GetZone ();
  1011.     SetZone (SystemZone ());
  1012.  
  1013.     // Get the driver data from the ID.
  1014.     pSBPDriverData = (SBPDriverDataPtr) sbpDriverID;
  1015.  
  1016.     // Close the driver.
  1017.     if (pSBPDriverData->driverOpened)
  1018.         CloseDriver (pSBPDriverData->driverRefNum);
  1019.  
  1020.     // Remove driver record from family list.
  1021.     pSearchSBPDriverData = gpSBPFamilyData->pSBPDriverList;
  1022.     pPrevSBPDriverData = nil;
  1023.     while ((pSearchSBPDriverData != nil) &&
  1024.            (pSearchSBPDriverData != pSBPDriverData))
  1025.     {
  1026.         pPrevSBPDriverData = pSearchSBPDriverData;
  1027.         pSearchSBPDriverData =
  1028.             pSearchSBPDriverData->pNextSBPDriverData;
  1029.     }
  1030.     if (pSearchSBPDriverData != nil)
  1031.     {
  1032.         if (pPrevSBPDriverData != nil)
  1033.         {
  1034.             pPrevSBPDriverData->pNextSBPDriverData =
  1035.                 pSBPDriverData->pNextSBPDriverData;
  1036.         }
  1037.         else
  1038.         {
  1039.             gpSBPFamilyData->pSBPDriverList =
  1040.                 pSBPDriverData->pNextSBPDriverData;
  1041.         }
  1042.     }
  1043.     gpSBPFamilyData->numSBPDrivers--;
  1044.  
  1045.     // Deallocate driver data record.
  1046.     PoolDeallocate ((Ptr) pSBPDriverData);
  1047.  
  1048.     // Switch zone back.
  1049.     SetZone (currentZone);
  1050. }
  1051.  
  1052.  
  1053. ////////////////////////////////////////////////////////////////////////////////
  1054. //
  1055. // SBPFindDriver
  1056. //
  1057. //   This routine finds the SBP driver corresponding to the given Name Registry
  1058. // entry.
  1059. //
  1060.  
  1061. static SBPDriverID    SBPFindDriver(
  1062.     RegEntryIDPtr                pRegEntryID)
  1063. {
  1064.     SBPDriverID                    sbpDriverID;
  1065.     SBPDriverDataPtr            pSBPDriverData;
  1066.     Boolean                        found;
  1067.  
  1068.     // Find driver that has matching name registry entry.
  1069.     pSBPDriverData = gpSBPFamilyData->pSBPDriverList;
  1070.     found = false;
  1071.     while ((pSBPDriverData != nil) && (!found))
  1072.     {
  1073.         if (RegistryEntryIDCompare (&(pSBPDriverData->deviceRegistryID), pRegEntryID))
  1074.             found = true;
  1075.         else
  1076.             pSBPDriverData = pSBPDriverData->pNextSBPDriverData;
  1077.     }
  1078.  
  1079.     // Set return value.
  1080.     if (found)
  1081.         sbpDriverID = (SBPDriverID) pSBPDriverData;
  1082.     else
  1083.         sbpDriverID = kInvalidSBPDriverID;
  1084.  
  1085.     return (sbpDriverID);
  1086. }
  1087.